#include "cmd-variables.h"

#include "console.h"
#include "value.h"
#include "variable.h"

bool cbInstrVar(int argc, char* argv[]) {
  if (IsArgumentsLessThan(argc, 2)) return false;
  char arg2[deflen] = "";  // var value (optional)
  if (argc > 2) strcpy_s(arg2, argv[2]);
  duint value = 0;
  int add = 0;
  if (*argv[1] == '$') add++;
  if (valfromstring(argv[1] + add, &value)) {
    dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid variable name \"%s\"\n"),
            argv[1]);
    return false;
  }
  if (!valfromstring(arg2, &value)) {
    dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid value \"%s\"\n"), arg2);
    return false;
  }
  if (!varnew(argv[1], value, VAR_USER)) {
    dprintf(QT_TRANSLATE_NOOP("DBG", "Error creating variable \"%s\"\n"),
            argv[1]);
    return false;
  } else {
    if (value > 15)
#ifdef _WIN64
      dprintf_untranslated("%s=%llX (%llud)\n", argv[1], value, value);
#else  // x86
      dprintf_untranslated("%s=%X (%ud)\n", argv[1], value, value);
#endif  //_WIN64
    else
#ifdef _WIN64
      dprintf_untranslated("%s=%llX\n", argv[1], value);
#else  // x86
      dprintf_untranslated("%s=%X\n", argv[1], value);
#endif  //_WIN64
  }
  return true;
}

bool cbInstrVarDel(int argc, char* argv[]) {
  if (IsArgumentsLessThan(argc, 2)) return false;
  if (!vardel(argv[1], false))
    dprintf(QT_TRANSLATE_NOOP("DBG", "Could not delete variable \"%s\"\n"),
            argv[1]);
  else
    dprintf(QT_TRANSLATE_NOOP("DBG", "Deleted variable \"%s\"\n"), argv[1]);
  return true;
}

bool cbInstrVarList(int argc, char* argv[]) {
  int filter = 0;
  if (argc > 1) {
    if (!_stricmp(argv[1], "USER"))
      filter = VAR_USER;
    else if (!_stricmp(argv[1], "READONLY"))
      filter = VAR_READONLY;
    else if (!_stricmp(argv[1], "SYSTEM"))
      filter = VAR_SYSTEM;
  }

  size_t cbsize = 0;
  if (!varenum(0, &cbsize)) {
    dputs(QT_TRANSLATE_NOOP("DBG", "No variables!"));
    return true;
  }
  Memory<VAR*> variables(cbsize, "cbInstrVarList:variables");
  if (!varenum(variables(), 0)) {
    dputs(QT_TRANSLATE_NOOP("DBG", "Error listing variables!"));
    return false;
  }

  GuiReferenceInitialize(
      GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Variables")));
  GuiReferenceAddColumn(
      2 * sizeof(duint),
      GuiTranslateText(QT_TRANSLATE_NOOP(
          "DBG", "Value (Hex)")));  // The GUI only follows address in column 0
  GuiReferenceAddColumn(30,
                        GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Variable")));
  GuiReferenceAddColumn(3 * sizeof(duint), GuiTranslateText(QT_TRANSLATE_NOOP(
                                               "DBG", "Value (Decimal)")));
  GuiReferenceAddColumn(20,
                        GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Property")));
  int varcount = (int)cbsize / sizeof(VAR);
  int realvarcount = 0;
  GuiReferenceSetRowCount(0);
  for (int i = 0; i < varcount; i++) {
    char value[32];
    if (variables()[i].alias.length()) continue;
    if (variables()[i].type != VAR_HIDDEN) {
      GuiReferenceSetRowCount(realvarcount + 1);
      GuiReferenceSetCellContent(realvarcount, 1, variables()[i].name.c_str());
#ifdef _WIN64
      sprintf_s(value, "%llX", variables()[i].value.u.value);
      GuiReferenceSetCellContent(realvarcount, 0, value);
      sprintf_s(value, "%llu", variables()[i].value.u.value);
      GuiReferenceSetCellContent(realvarcount, 2, value);
#else  // x86
      sprintf_s(value, "%X", variables()[i].value.u.value);
      GuiReferenceSetCellContent(realvarcount, 0, value);
      sprintf_s(value, "%u", variables()[i].value.u.value);
      GuiReferenceSetCellContent(realvarcount, 2, value);
#endif  //_WIN64
      const char* szType;
      switch (variables()[i].type) {
        case VAR_USER:
          szType = QT_TRANSLATE_NOOP("DBG", "User Variable");
          break;
        case VAR_SYSTEM:
          szType = QT_TRANSLATE_NOOP("DBG", "System Variable");
          break;
        case VAR_READONLY:
          szType = QT_TRANSLATE_NOOP("DBG", "Read Only Variable");
          break;
        default:  // other variables
          szType = QT_TRANSLATE_NOOP("DBG", "System Variable");
          break;
      }
      GuiReferenceSetCellContent(realvarcount, 3, GuiTranslateText(szType));
      realvarcount++;
    }
  }
  GuiReferenceAddCommand(GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Delete")),
                         "vardel $1");
  GuiReferenceReloadData();
  return true;
}